﻿using System;
using System.Drawing;
using System.Windows.Forms;
using Emgu.CV;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using Emgu.CV.Structure;


namespace CameraCapture {
    public partial class CamCap : UserControl {
        #region EventHanlers
        public EventHandler NewPic;
        public EventHandler LogUpdated;
        #endregion

        #region Status Variables
        private bool mIsRunning;

        #endregion

        #region Threads
        private Thread mCamCapT;
        #endregion

        #region Main Variables
        private string mPathToSave;    // a path that represents the last picture saved in the discs
        private long mPicNo;
        private string mTmpPath;
        private Image mBmap;
        public string GetPathToSave {
            get { return mPathToSave; }
        }

        private List<string> log;

        public List<string> GetLog {
            get { return log; }
        }
        private string AddLogEntry {
            set {
                log.Add(DateTime.Now.ToShortTimeString() + " " + value);
                if (LogUpdated != null)
                    LogUpdated.Invoke(log, null);
            }
        }
        #endregion

        #region Constructors
        public CamCap() {
            InitializeComponent();
            InitThread();
            NewPic += DoUpdate;
            mPicNo = 0;
            mIsRunning = false;
            log = new List<string>();
        }
        #endregion

        #region Thread implementation
        private void InitThread() {
            mCamCapT = new Thread(CamCapThread);
        }
        public void CamCapThread() {
            try {
                using (Capture cap = new Capture()) {
                    while (mIsRunning) {
                        // Do whatever it's need to be done     
                        Image<Bgr, byte> frame = cap.QueryFrame();
                        if (frame != null) {
                            NewPic.Invoke(frame.Bitmap, new EventArgs());
                            //addLogEntry = "Picture captured.";
                        }
                        Thread.Sleep(30);
                    }
                }
            } catch (NullReferenceException) {
                AddLogEntry = "No camera found!";
                /*No camera */
            }
        }
        #endregion
        private void DoUpdate(object pic, EventArgs e) {
            lock (this) {
                mBmap = (Image)((Bitmap)pic).Clone();
                if (checkBoxShowPics.Checked) {
                    pictureBox.Image = mBmap;
                    AddLogEntry = "PictureBox updated.";
                }
            }
            if (checkBoxSaveToFile.Checked) {
                try {
                    mTmpPath = mPathToSave;
                    if (checkBoxSaveAll.Checked) {
                        mTmpPath = mPathToSave.Substring(0, mPathToSave.Length - 4);
                        mTmpPath += mPicNo++.ToString() + mPathToSave.Substring(mPathToSave.Length - 4);
                    }
                    using (FileStream stream = new FileStream(mTmpPath, FileMode.Create)) {
                        mBmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                    }
                    AddLogEntry = "Pic saved as :" + mTmpPath;
                } catch (IndexOutOfRangeException) {
                    AddLogEntry = "String indexing error.";
                } catch {
                    //check here why it failed and ask user to retry if the file is in use.
                    AddLogEntry = "Can't access to file:" + mTmpPath;
                }
            }
        }

        private void StartButtonClick(object sender, EventArgs e) {
            mIsRunning = !mIsRunning;
            startButton.Text = (mIsRunning ? "Stop" : "Start");
            if (!mCamCapT.IsAlive) {
                if (mCamCapT.ThreadState != ThreadState.Unstarted) InitThread();

                mCamCapT.Start();
                checkBoxSaveAll.Enabled = false;
                checkBoxSaveToFile.Enabled = false;
                checkBoxShowPics.Enabled = false;
            } else {
                mCamCapT.Join();
                checkBoxSaveAll.Enabled = true;
                checkBoxSaveToFile.Enabled = true;
                checkBoxShowPics.Enabled = true;
            }
        }
        public void Stop() {
            mIsRunning = false;
            //NewPic -= doUpdate;
            //wait until its realy stops
            try {
                mCamCapT.Join();
                AddLogEntry = "Thread Stopped";
            } catch (ThreadStateException) {
                //thread never run
            }
        }
        private void ShowCheckBoxCheckedChanged(object sender, EventArgs e) {
        }

        private void CheckBoxSaveToFileCheckedChanged(object sender, EventArgs e) {
            if (checkBoxSaveToFile.Checked) {
                //SaveFileDialog ofd = new SaveFileDialog {Filter = "jpeg|*.jpg"};
                mPathToSave = Directory.GetCurrentDirectory() + @"\http\pics\";
                mPathToSave += "frame.jpg";
                checkBoxSaveAll.Enabled = true;
                AddLogEntry = "Saving path set to " + mPathToSave;
                //if (wereRun) {
                //    IsRunning = true;
                //    NewPic += doUpdate;                    
                //    camCapT.Start();
                //    addLogEntry = "Capturing started.";
                //}
            } else {
                checkBoxSaveAll.Enabled = false;
            }
        }

        private void CheckBoxSaveToFileMouseDown(object sender, MouseEventArgs e) {
            Stop();
        }
    }
}
